package com.huxi.lang.validation.predicate;

import static com.huxi.lang.type.VTypeUtils.compareToZero;
import static com.huxi.lang.type.VTypeUtils.parseNumber;

import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Map;

public class VPredicateFactory {

	public static final VPredicate NotNull = new VPredicate() {
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			return t != null;
		}

		@Override
		public boolean test(Object t) {
			return t != null;
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.IsNull;
		}

		@Override
		public boolean zeroJdbcOperatorParameter() {
			return true;
		}

		@Override
		public String toString() {
			return "NotNull";
		}
	};

	public static final VPredicate IsNull = new VPredicate() {
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			return t == null;
		}

		@Override
		public boolean test(Object t) {
			return t == null;
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.NotNull;
		}

		@Override
		public boolean zeroJdbcOperatorParameter() {
			return true;
		}

		@Override
		public String toString() {
			return "IsNull";
		}
	};

	public static final VPredicate NotBlank = new VPredicate() {
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			if (t instanceof CharSequence) {
				CharSequence s = (CharSequence) t;
				for (int i = 0; i < s.length(); i++) {
					if (!Character.isWhitespace(s.charAt(i))) {
						return true;
					}
				}
				return false;
			}
			return t == null ? valueIfNull : valueIfIllegalType;
		}

		@Override
		public boolean test(Object t) {
			return test(t, false, true);
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.IsBlank;
		}

		@Override
		public String toString() {
			return "NotBlank";
		}
	};

	public static final VPredicate IsBlank = new VPredicate() {
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			if (t instanceof CharSequence) {
				CharSequence s = (CharSequence) t;
				for (int i = 0; i < s.length(); i++) {
					if (!Character.isWhitespace(s.charAt(i))) {
						return false;
					}
				}
				return true;
			}
			return t == null ? valueIfNull : valueIfIllegalType;
		}

		@Override
		public boolean test(Object t) {
			return test(t, false, true);
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.NotBlank;
		}

		@Override
		public String toString() {
			return "IsBlank";
		}
	};

	public static final VPredicate NotEmpty = new VPredicate() {
		@SuppressWarnings("rawtypes")
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			if (t instanceof CharSequence) {
				return ((CharSequence) t).length() != 0;
			}
			if (t instanceof Collection) {
				return ((Collection) t).size() != 0;
			}
			if (t instanceof Map) {
				return ((Map) t).size() != 0;
			}
			if (t.getClass().isArray()) {
				return Array.getLength(t) != 0;
			}
			return t == null ? valueIfNull : valueIfIllegalType;
		}

		@Override
		public boolean test(Object t) {
			return test(t, false, true);
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.IsEmpty;
		}

		@Override
		public String toString() {
			return "NotEmpty";
		}
	};

	public static final VPredicate IsEmpty = new VPredicate() {
		@SuppressWarnings("rawtypes")
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			if (t instanceof CharSequence) {
				return ((CharSequence) t).length() == 0;
			}
			if (t instanceof Collection) {
				return ((Collection) t).size() == 0;
			}
			if (t instanceof Map) {
				return ((Map) t).size() == 0;
			}
			if (t.getClass().isArray()) {
				return Array.getLength(t) == 0;
			}
			return t == null ? valueIfNull : valueIfIllegalType;
		}

		@Override
		public boolean test(Object t) {
			return test(t, false, true);
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.NotEmpty;
		}

		@Override
		public String toString() {
			return "IsEmpty";
		}
	};

	public static final VPredicate Positive = new VPredicate() {
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			if (t instanceof Number) {
				return compareToZero((Number) t) > 0;
			}
			if (t instanceof CharSequence) {
				try {
					return compareToZero(parseNumber(t.toString())) > 0;
				} catch (Exception e) {

				}
			}
			return t == null ? valueIfNull : valueIfIllegalType;
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.ZeroOrNegative;
		}

		@Override
		public String toString() {
			return "Positive";
		}
	};

	public static final VPredicate ZeroOrNegative = new VPredicate() {
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			if (t instanceof Number) {
				return compareToZero((Number) t) <= 0;
			}
			if (t instanceof CharSequence) {
				try {
					return compareToZero(parseNumber(t.toString())) <= 0;
				} catch (Exception e) {

				}
			}
			return t == null ? valueIfNull : valueIfIllegalType;
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.Positive;
		}

		@Override
		public String toString() {
			return "ZeroOrNegative";
		}
	};

	public static final VPredicate Negative = new VPredicate() {
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			if (t instanceof Number) {
				return compareToZero((Number) t) < 0;
			}
			if (t instanceof CharSequence) {
				try {
					return compareToZero(parseNumber(t.toString())) < 0;
				} catch (Exception e) {

				}
			}
			return t == null ? valueIfNull : valueIfIllegalType;
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.ZeroOrPositive;
		}

		@Override
		public String toString() {
			return "Negative";
		}
	};

	public static final VPredicate ZeroOrPositive = new VPredicate() {
		@Override
		public boolean test(Object t, boolean valueIfNull, boolean valueIfIllegalType) {
			if (t instanceof Number) {
				return compareToZero((Number) t) >= 0;
			}
			if (t instanceof CharSequence) {
				try {
					return compareToZero(parseNumber(t.toString())) >= 0;
				} catch (Exception e) {

				}
			}
			return t == null ? valueIfNull : valueIfIllegalType;
		}

		@Override
		public VPredicate negate() {
			return VPredicateFactory.Negative;
		}

		@Override
		public String toString() {
			return "ZeroOrPositive";
		}
	};

	public VPredicate notNull() {
		return NotNull;
	}

	public VPredicate isNull() {
		return IsNull;
	}

	public VPredicate notBlank() {
		return NotBlank;
	}

	public VPredicate isBlank() {
		return IsBlank;
	}

	public VPredicate notEmpty() {
		return NotEmpty;
	}

	public VPredicate isEmpty() {
		return IsEmpty;
	}

	public VPredicate positive() {
		return Positive;
	}

	public VPredicate negative() {
		return Negative;
	}

	public VPredicate zeroOrPositive() {
		return ZeroOrPositive;
	}

	public VPredicate zeroOrNegative() {
		return ZeroOrNegative;
	}

}
